package pin

import (
	"context"
	"fmt"
)

type GPIOManager struct {
	ctx    context.Context
	pinMap map[int]*Pin
}

func New(ctx context.Context) (manager *GPIOManager) {

	manager = &GPIOManager{
		ctx:    ctx,
		pinMap: make(map[int]*Pin),
	}
	go func() {
		manager.waitClose()
	}()
	return
}

func (g *GPIOManager) OpenPin(number int, dir Direction) (pin *Pin, err error) {
	pin, err = OpenPin(number, dir)

	if err != nil {
		return
	}
	g.savePin(pin)
	return
}

func (g *GPIOManager) GetPin(number int) (pin *Pin, err error) {
	pin, ok := g.pinMap[number]
	if !ok {
		err = fmt.Errorf("404")
		return
	}
	return
}

func (g *GPIOManager) GetPinMap() map[int]*Pin {

	return g.pinMap
}

func (g *GPIOManager) savePin(pin *Pin) {
	if g.pinMap == nil {
		return
	}
	g.pinMap[pin.PinNumber()] = pin
}

func (g *GPIOManager) waitClose() {
	for {
		select {
		case <-g.ctx.Done():
			g.closeAll()
			return
		}
	}
}

func (g *GPIOManager) closeAll() {
	if g.pinMap == nil {
		return
	}
	for _, pin := range g.pinMap {
		if pin == nil {
			continue
		}
		_ = pin.Close()
	}
}
